
#include "Listener.h"
#include "../../loop/LoopService.h"
#include "../../common/ErrorCode.h"
#include "event2/event.h"
#include "event2/listener.h"
#include "event2/util.h"


Listener::Listener(LoopService& base)
{
    loop_ = &base;
    handler_ = nullptr;
}


Listener::~Listener()
{
    close();
}

void Listener::close()
{
    if (handler_) {
        evconnlistener_free(handler_);
    }
    handler_ = nullptr;
}

std::error_code Listener::listen(const std::string& addr)
{
    struct sockaddr_storage listen_on_addr = {};
    int socklen = sizeof(listen_on_addr);

    if (evutil_parse_sockaddr_port(addr.c_str(), (struct sockaddr*)&listen_on_addr, &socklen) < 0)
    {
        return std::make_error_code(std::errc::invalid_argument);
    }


    handler_ = evconnlistener_new_bind(loop_->event_base(), listener_cb, (void*)this,
        LEV_OPT_CLOSE_ON_FREE | LEV_OPT_CLOSE_ON_EXEC | LEV_OPT_REUSEABLE,
        -1, (struct sockaddr*)&listen_on_addr, socklen);

    if (!handler_) {
        return make_socket_error_code(EVUTIL_SOCKET_ERROR());
    }
    return std::error_code();
}


void Listener::listener_cb(struct evconnlistener *, ez_socket_t fd,
    struct sockaddr *addr, int socklen, void *arg)
{
    auto self = (Listener*)arg;
    if (self->callback_) {
        self->callback_(fd, addr, socklen);
    }
}

